﻿#ifndef CIPHERUTILS_H
#define CIPHERUTILS_H

#include <vector>
#include <memory>
#include <string>

#include <openssl/rand.h>
#include <openssl/aes.h>
#include <openssl/pem.h>
#include <openssl/ec.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/kdf.h>

class CipherUtils {
public:
    // 单例模式
    static CipherUtils& getInstance();

    // 删除拷贝构造函数和拷贝赋值操作符
    CipherUtils(CipherUtils const&) = delete;
    CipherUtils& operator=(CipherUtils const&) = delete;

    /*生成一个aes密钥，使用CBC模式*/
    std::vector<std::shared_ptr<unsigned char[]>> AES_generate();
    /*使用aes加密*/
    std::pair<std::shared_ptr<unsigned char[]>, int> AES_Encrypt(const char* plainText,
                                                                 int textLength,
                                                                 unsigned char* key,
                                                                 unsigned char* iv);

    /*使用aes加密*/
    std::pair<std::shared_ptr<unsigned char[]>, int> AES_Encrypt(std::shared_ptr<char[]> plainText,
                                                                 int textLength,
                                                                 std::shared_ptr<unsigned char[]> key,
                                                                 std::shared_ptr<unsigned char[]> iv);

    /*使用aes加密*/
    std::pair<std::shared_ptr<unsigned char[]>, int> AES_Encrypt(const std::string& plainText,
                                                                 std::shared_ptr<unsigned char[]> key,
                                                                 std::shared_ptr<unsigned char[]> iv);

    /*使用aes解密*/
    std::pair<std::shared_ptr<unsigned char[]>, int> AES_Decrypt(unsigned char* cipherText,
                                                                 int cipherLength,
                                                                 unsigned char* key,
                                                                 unsigned char* iv);

    /*使用aes解密*/
    std::pair<std::shared_ptr<unsigned char[]>, int> AES_Decrypt(std::shared_ptr<unsigned char[]> cipherText,
                                                                 int cipherLength,
                                                                 std::shared_ptr<unsigned char[]> key,
                                                                 std::shared_ptr<unsigned char[]> iv);

    /*生成ecc密钥对，生成pem格式的密钥对，first：公钥，second：私钥*/
    std::pair<std::string, std::string> ECC_generate();
    /*计算ECDH密钥，传入的是自已的密钥与目标的公钥，返回值是ECDH密钥*/
    std::pair<std::shared_ptr<unsigned char[]>, int> ECDH_computeKey(const std::string& privateKey,
                                                                     const std::string& publicKey);
    /*使用ECHD共享密钥计算AES256密钥*/
    std::vector<std::shared_ptr<unsigned char[]>> AES_generateFromECDHSharedKey(std::shared_ptr<unsigned char[]> ECDHKey,
                                                                                int ECDHKeyLength);

    /*二进制向base64转换*/
    std::string Base64_Encode(const unsigned char* binary, int length);

    /*base64向二进制转换*/
    std::pair<std::shared_ptr<unsigned char[]>, int> Base64_Decode(const std::string& base64String);

    /*calc encrypted length*/
    size_t calculateAESEncryptedLength(size_t plainTextLength);
    /*calc sha256*/
    std::string SHA256_calculate(const std::string& input);

private:
    CipherUtils();
    ~CipherUtils();

    // 读取ECC的pem格式的公钥并返回对应的对象
    EC_KEY* ECC_readPublicKeyFromString(const std::string& publicKeyPEM);

    // 读取ECC的pem格式的私钥并返回对应的对象
    EC_KEY* ECC_readPrivateKeyFromString(const std::string& privateKeyPEM);

};

#endif // CIPHERUTILS_H
